#include "exception.hpp"

namespace fur
{

   namespace
   {
      // default flag is exception
      ExceptionFlag rarheadflag = ExceptionFlag::EXCEPTION;
      ExceptionFlag headcrcflag = ExceptionFlag::EXCEPTION;
      ExceptionFlag filecrcflag = ExceptionFlag::EXCEPTION;
   }

   namespace 
   {
      const char *unknownmes = "Unknown exception";
      const char *allocationmes = "Allocating memory failed";
      const char *filereadmes = "File read failed";
      const char *rarheadmes = "RAR Head is broken";
      const char *headcrcmes = "Head CRC check failed";
      const char *filecrcmes = "File CRC check failed";
      const char *unpackmes = "Unpack failed";
      const char *unsupportmes = "Unsupported function";

      const char *unknownname = "fur::EUnknown";
      const char *allocationname = "fur::EAllocation";
      const char *filereadname = "fur::EFileread";
      const char *rarheadname = "fur::ERarhead";
      const char *headcrcname = "fur::EHeadcrc";
      const char *filecrcname = "fur::EFilecrc";
      const char *unpackname = "fur::EUnpack";
      const char *unsupportname = "fur::EUnsupport";
   }

   ExceptionFlag &ef_rarhead() throw()
   {
      return rarheadflag;
   }
   
   ExceptionFlag &ef_headcrc() throw()
   {
      return headcrcflag;
   }
   
   ExceptionFlag &ef_filecrc() throw()
   {
      return filecrcflag;
   }

   Exception::Exception(ExceptionType exceptiontype, const char *functionname, const char *amessage) throw()
      :etype(exceptiontype), fname(functionname), mes(amessage)
   {
   }
   
   const char *Exception::function() const throw()
   {
      return fname;
   }
   
   ExceptionType Exception::type() const throw()
   {
      return etype;
   }
   
   const char *Exception::message() const throw()
   {
      return mes;
   }

   std::ostream &Exception::output(std::ostream &os) const throw()
   {
      os << "Exception: " << mes << " in Function: " << fname << std::endl;
      return os;
   }

   EUnknown::EUnknown(const char *funcname) throw()
      :Exception(ExceptionType::UNKNOWN, funcname, unknownmes)
   {
   }

   const char *EUnknown::what() const throw()
   {
      return unknownname;
   }

   EAllocation::EAllocation(const char *funcname) throw()
      :Exception(ExceptionType::ALLOCATION, funcname, allocationmes)
   {
   }
   
   const char *EAllocation::what() const throw()
   {
      return allocationname;
   }
   
   EFileread::EFileread(const char *funcname) throw()
      :Exception(ExceptionType::FILEREAD, funcname, filereadmes)
   {
   }
   
   const char *EFileread::what() const throw()
   {
      return filereadname;
   }
   
   ERarhead::ERarhead(const char *funcname) throw()
      :Exception(ExceptionType::RARHEAD, funcname, rarheadmes)
   {
   }
   
   const char *ERarhead::what() const throw()
   {
      return rarheadname;
   }
   
   EHeadcrc::EHeadcrc(const char *funcname) throw()
      :Exception(ExceptionType::HEADCRC, funcname, headcrcmes)
   {
   }
   
   const char *EHeadcrc::what() const throw()
   {
      return headcrcname;
   }
   
   EFilecrc::EFilecrc(const char *funcname) throw()
      :Exception(ExceptionType::FILECRC, funcname, filecrcmes)
   {
   }
   
   const char *EFilecrc::what() const throw()
   {
      return filecrcname;
   }
   
   EUnpack::EUnpack(const char *funcname) throw()
      :Exception(ExceptionType::UNPACK, funcname, unpackmes)
   {
   }
   
   const char *EUnpack::what() const throw()
   {
      return unpackname;
   }
   
   EUnsupport::EUnsupport(const char *funcname) throw()
      :Exception(ExceptionType::UNSUPPORT, funcname, unsupportmes)
   {
   }

   const char *EUnsupport::what() const throw()
   {
      return unsupportname;
   }
   
} // end of namespace fur
